﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bridge.Workflow.Application.Contracts;
using Bridge.Workflow.Domain;
using Bridge.Workflow.Domain.Workflows;
using Bridge.Workflow.Workflows.Dtos;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.Linq;
using Volo.Abp.Users;

namespace Bridge.Workflow.Application
{
    /// <summary>
    /// 工作流流程定义管理
    /// </summary>
    public class WorkflowDesignService : CrudAppService<PersistedWorkflowDefinition,
        WorkflowDesignInfo,
        string,
        WorkflowListInput,
        WorkflowDesignInfo,
        WorkflowDesignInfo>
    {
        private readonly IGuidGenerator _guidGenerator;
        private readonly IAbpWorkflowManager _abpWorkflowManager;
        private readonly ICurrentUser _currentUser;
        private readonly IAsyncQueryableExecuter _asyncQueryableExecuter;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="workflowRepository"></param>
        /// <param name="abpWorkflowManager"></param>
        /// <param name="guidGenerator"></param>
        /// <param name="currentUser"></param>
        public WorkflowDesignService(
            IRepository<PersistedWorkflowDefinition, string> repository,
            IAbpWorkflowManager abpWorkflowManager,
            IAsyncQueryableExecuter asyncQueryableExecuter,
            IGuidGenerator guidGenerator,
            ICurrentUser currentUser) : base(repository)
        {
            _asyncQueryableExecuter = asyncQueryableExecuter;
            _abpWorkflowManager = abpWorkflowManager;
            _guidGenerator = guidGenerator;
            _currentUser = currentUser;
        }

        /// <summary>
        /// 获取所有流程定义分组
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetAllGroupAsync()
        {
            var data = await _asyncQueryableExecuter.ToListAsync((await Repository.GetQueryableAsync()).GroupBy(u => u.Group).Select(u => u.Key));
            return data.Where(u => !u.IsNullOrEmpty());
        }

        /// <summary>
        /// 获取所有流程定义步骤
        /// </summary>
        /// <returns></returns>
        public IEnumerable<AbpWorkflowStepBody> GetAllStepBodys()
        {
            return _abpWorkflowManager.GetAllStepBodys();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        protected  IQueryable<PersistedWorkflowDefinition> CreateFilterQuery(WorkflowListInput input)
        {
            return  base.Repository.GetQueryableAsync().Result;
        }

        /// <summary>
        /// 获取所有分组的流程定义
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Dictionary<string, IEnumerable<WorkflowDesignInfo>>> GetAllWithGroupAsync(WorkflowListInput input)
        {
            var list = await _asyncQueryableExecuter.ToListAsync(this.CreateFilterQuery(input).Select(u => u));
            return list.GroupBy(u => u.Group).OrderBy(i => i.Key).ToDictionary(u => u.Key, u => u.Select(i => (WorkflowDesignInfo)i));
        }

        /// <summary>
        /// 获取所有流程定义
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<PagedResultDto<WorkflowDesignInfo>> GetListAsync(WorkflowListInput input)
        {
            return await base.GetListAsync(input);
        }

        /// <summary>
        /// 获取流程定义
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override async Task<WorkflowDesignInfo> GetAsync(string id)
        {
            return await Repository.FirstOrDefaultAsync(x => x.Id == id);
        }

        /// <summary>
        /// 创建流程定义
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<WorkflowDesignInfo> CreateAsync(WorkflowDesignInfo input)
        {
            //var entity = await ApplyCreate(input);
            if (string.IsNullOrEmpty(input.Id)) input.Id = _guidGenerator.Create().ToString();

            _abpWorkflowManager.LoadDefinition((PersistedWorkflowDefinition)input);

            var entity = (PersistedWorkflowDefinition)input;
            entity.CreatorId = _currentUser.Id;
            entity.LastModificationTime = DateTime.Now;
            entity.LastModifierId = _currentUser.Id;
            //entity.IsDeleted = false;

            await Repository.InsertAsync(entity, true, default);

            return null;
        }

        /// <summary>
        /// 更新流程定义
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async override Task<WorkflowDesignInfo> UpdateAsync(string id, WorkflowDesignInfo input)
         {
            var en = new WorkflowDesignInfoUpdate();
            en.Color = input.Color;
            en.Group = input.Group;
            en.Icon = input.Icon;
            en.Title = input.Title;
            en.Version = input.Version;
            en.Description = input.Description;
            en.Inputs = input.Inputs;
            en.Nodes = input.Nodes;
            var entity = await ApplyUpdate(input);
            return await _abpWorkflowManager.UpdateAsync(entity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        protected virtual async Task<PersistedWorkflowDefinition> ApplyUpdate(WorkflowDesignInfo input)
        {
            var entity =await Repository.FirstOrDefaultAsync(u => u.Id == input.Id && u.Version == input.Version);
            //entity = ObjectMapper.Map(input, entity);
            entity.Color = input.Color;
            entity.Group = input.Group;
            entity.Icon = input.Icon;
            entity.Title = input.Title;
            entity.Version = input.Version;
            entity.Description = input.Description;
            entity.Inputs = input.Inputs;
            entity.Nodes = input.Nodes;
            return entity;
        }

        /// <summary>
        /// 删除流程定义
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task DeleteAsync(string id)
        {
            await base.DeleteAsync(id);
        }
    }
}
